// Package data 提供评论的无限极评论（树形评论）数据结构和核心方法
package data

import (
	"context"
	"time"
	"user/internal/conf"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
)

// Comment 表示一条对文章的评论，支持无限极嵌套
// ParentID 为空字符串表示顶级评论
// ArticleID 表示所属文章
type Comment struct {
	ID         primitive.ObjectID `bson:"_id,omitempty" json:"id"`        // 评论ID
	ArticleID  string             `bson:"article_id" json:"article_id"`   // 所属文章ID
	ParentID   string             `bson:"parent_id" json:"parent_id"`     // 父评论ID，顶级为空字符串
	UserID     string             `bson:"user_id" json:"user_id"`         // 评论用户ID
	Content    string             `bson:"content" json:"content"`         // 评论内容
	CreatedAt  int64              `bson:"created_at" json:"created_at"`   // 创建时间戳
	LikeCount  int64              `bson:"like_count" json:"like_count"`   // 点赞数
	ReplyCount int64              `bson:"reply_count" json:"reply_count"` // 回复数
	Children   []*Comment         `bson:"-" json:"children,omitempty"`    // 子评论
}

// CommentNode 用于返回树形结构
// Children 为子评论节点
type CommentNode struct {
	Comment  *Comment       `json:"comment"`  // 当前评论
	Children []*CommentNode `json:"children"` // 子评论
}

// CommentRepo 评论仓库，封装MongoDB操作
type CommentRepo struct {
	coll *mongo.Collection // MongoDB集合
}

// NewCommentRepo 创建评论仓库实例，支持 kratos wire 依赖注入
// 参数：
//
//	client - MongoDB客户端
//	c      - 配置信息（包含MongoDB配置）
func NewCommentRepo(client *mongo.Client, c *conf.Data) *CommentRepo {
	db := client.Database(c.Mongo.Database)
	return &CommentRepo{
		coll: db.Collection(c.Mongo.Collection),
	}
}

// AddComment 新增一条评论
// req.ParentID 应为父评论的 ObjectID.Hex()，顶级为 ""
func (r *CommentRepo) AddComment(ctx context.Context, c *Comment) (*Comment, error) {
	c.LikeCount = 0
	c.ReplyCount = 0
	c.CreatedAt = time.Now().Unix()
	// 保证 ParentID 为空字符串或合法 ObjectID.Hex()
	if c.ParentID == "0" || c.ParentID == "nil" {
		c.ParentID = ""
	}
	res, err := r.coll.InsertOne(ctx, c)
	if err != nil {
		return nil, err
	}
	c.ID = res.InsertedID.(primitive.ObjectID)
	return c, nil
}

// GetCommentsTree 查询某文章下的所有评论，分页返回顶级评论及其子树
func (r *CommentRepo) GetCommentsTree(ctx context.Context, articleID string, page, pageSize int32) ([]*Comment, int64, error) {
	filter := bson.M{"article_id": articleID}
	cursor, err := r.coll.Find(ctx, filter)
	if err != nil {
		return nil, 0, err
	}
	var allComments []*Comment
	if err := cursor.All(ctx, &allComments); err != nil {
		return nil, 0, err
	}
	// 组装树，只分页顶级评论
	var roots []*Comment
	idMap := make(map[string]*Comment)
	for _, c := range allComments {
		idMap[c.ID.Hex()] = c
	}
	for _, c := range allComments {
		if c.ParentID == "" {
			roots = append(roots, c)
		} else if parent, ok := idMap[c.ParentID]; ok {
			parent.Children = append(parent.Children, c)
		}
	}
	total := int64(len(roots))
	start := int(pageSize) * (int(page) - 1)
	end := start + int(pageSize)
	if start > len(roots) {
		return []*Comment{}, total, nil
	}
	if end > len(roots) {
		end = len(roots)
	}
	return roots[start:end], total, nil
}

// buildCommentTree 将评论列表组装为树形结构
func buildCommentTree(comments []*Comment) []*CommentNode {
	idMap := make(map[primitive.ObjectID]*CommentNode)
	var roots []*CommentNode
	// 先全部转为节点
	for _, c := range comments {
		node := &CommentNode{Comment: c}
		idMap[c.ID] = node
	}
	// 组装树
	for _, node := range idMap {
		if node.Comment.ParentID == "" {
			roots = append(roots, node)
		} else {
			// 将 ParentID 字符串转换为 primitive.ObjectID 类型
			parentID, err := primitive.ObjectIDFromHex(node.Comment.ParentID)
			if err != nil {
				// 转换失败，可能是无效的 ObjectID，跳过该节点
				continue
			}
			if parent, ok := idMap[parentID]; ok {
				parent.Children = append(parent.Children, node)
			}
		}
	}
	return roots
}
